home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Super Models
/
Hot Super Models.iso
/
unix
/
x11
/
xv200.tar
/
xv-2.00
/
xvps.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-02
|
29KB
|
1,077 lines
/*
* xvps.c - Postscript dialog box, file output functions
*
* callable functions:
*
* CreatePSD(geom) - creates the psW window. Doesn't map it.
* PSDialog() - maps psW
* PSCheckEvent(event) - called by event handler
* PSSaveParams(str,int) - tells PSDialog what to do when 'Ok' clicked
* PSResize() - called whenever ePic changes size
*/
/*
* Copyright 1989, 1990, 1991, 1992 by John Bradley and
* The University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any expressed or implied warranty.
*
* The author may be contacted via:
* US Mail: John Bradley
* GRASP Lab, Room 301C
* 3401 Walnut St.
* Philadelphia, PA 19104
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
#include "xv.h"
#define PSWIDE 431
#define PSHIGH 340
#define PMAX 200 /* size of square that a 'page' has to fit into */
#define PS_NBUTTS 6
#define PS_BOK 0
#define PS_BCANC 1
#define PS_BCENT 2
#define PS_BMAX 3
#define PS_BPOSX 4
#define PS_BPOSY 5
/* paperRB indicies */
#define PSZ_NORM 0
#define PSZ_A4 1
#define PSZ_B5 2
#define PSZ_LEGAL 3
#define PSZ_BSIZE 4
/* orientRB indicies */
#define ORNT_PORT 0
#define ORNT_LAND 1
#define BUTTH 24
#define IN2CM 2.54
#define PIX2INCH 72.0 /* # of pixels per inch, at 100% scaling */
#ifdef __STDC__
static void drawPSD(int, int, int, int);
static void drawPosStr();
static void drawSizeStr();
static void drawResStr();
static void drawPage();
static void clickPSD(int, int);
static void clickPage(int, int);
static void doCmd(int);
static void changedScale(void);
static void setScale(void);
static void changedPaper(void);
static void setPaper(void);
static void drawIRect(int);
static void centerImage(void);
static void maxImage(void);
static void moveImage(double, double);
static void writePS(void);
static void psColorImage();
static void epsPreview();
static int writeBWStip(FILE *, byte *, char *);
#else
static void drawPSD(), drawPosStr(), drawSizeStr(), drawResStr();
static void drawPage(), clickPSD(), clickPage(), doCmd(), changedScale();
static void setScale(), changedPaper(), setPaper(), drawIRect();
static void centerImage(), maxImage(), moveImage(), writePS(), psColorImage();
static void epsPreview();
static int writeBWStip();
#endif
/* local variables */
static Window pageF;
static DIAL xsDial, ysDial;
static RBUTT *orientRB, *paperRB;
static CBUTT lockCB;
static BUTT psbut[PS_NBUTTS];
static double sz_inx, sz_iny; /* image size, in inches */
static double pos_inx, pos_iny; /* top-left offset of image, in inches */
static int dpix, dpiy; /* # of image pixels per inch */
static int tracking=0; /* used in changedScale */
static int posxType, posyType;
/* sizes of pages in inches */
static double paperSize[5][2] = { { 8.500, 11.000}, /* US NORMAL */
{ 8.267, 11.811}, /* A4 */
{ 7.283, 10.630}, /* B5 */
{ 8.500, 14.000}, /* US LEGAL */
{11.000, 17.000}}; /* B-size */
static double psizex, psizey; /* current paper size, in inches */
static double in2pix; /* inch to pixels in 'pageF' */
static XRectangle pageRect; /* bounding rect of page, in screen coords */
static char *filename; /* filename to save to */
static int colorType; /* value of 'Colors' rbutt in dir box */
static int firsttime=1; /* first time PSDialog being opened ? */
/***************************************************/
void CreatePSD(geom)
char *geom;
{
CARD32 data[2];
Atom prop;
psW = CreateWindow("xv postscript", geom, PSWIDE, PSHIGH, infofg, infobg);
if (!psW) FatalError("can't create postscript window!");
data[0] = (CARD32) XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
data[1] = (CARD32) time((long *)0);
prop = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE),
XChangeProperty(theDisp, psW, prop, prop,
32, PropModeReplace, (unsigned char *) data, 2);
pageF = XCreateSimpleWindow(theDisp, psW, 20,30, PMAX+1,PMAX+1,
1,infofg,infobg);
if (!pageF) FatalError("couldn't create frame windows");
XSetWindowBackgroundPixmap(theDisp, pageF, grayTile);
XSelectInput(theDisp, pageF, ExposureMask | ButtonPressMask);
XSelectInput(theDisp, psW, ExposureMask | ButtonPressMask | KeyPressMask);
DCreate(&xsDial, psW, 240, 30, 80, 100, 10, 800, 100, 5,
infofg, infobg, "Width", "%");
DCreate(&ysDial, psW, 331, 30, 80, 100, 10, 800, 100, 5,
infofg, infobg, "Height", "%");
xsDial.drawobj = changedScale;
ysDial.drawobj = changedScale;
CBCreate(&lockCB, psW, 319, 136, "", infofg, infobg);
lockCB.val = 1;
orientRB = RBCreate(NULL, psW, 36, 240+18, "Portrait", infofg, infobg);
RBCreate(orientRB, psW, 36+80, 240+18, "Landscape", infofg, infobg);
paperRB = RBCreate(NULL, psW, 36, 240+18+36, "8.5\"x11\"", infofg, infobg);
RBCreate(paperRB, psW, 36+80, 240+18+36, "A4", infofg, infobg);
RBCreate(paperRB, psW, 36+154, 240+18+36, "B5", infofg, infobg);
RBCreate(paperRB, psW, 36, 240+36+36, "8.5\"x14\"", infofg, infobg);
RBCreate(paperRB, psW, 36+80, 240+36+36, "11\"x17\"", infofg, infobg);
BTCreate(&psbut[PS_BOK], psW, PSWIDE-160, PSHIGH-10-BUTTH, 60, BUTTH,
"Ok", infofg, infobg);
BTCreate(&psbut[PS_BCANC], psW, PSWIDE-80, PSHIGH-10-BUTTH, 60, BUTTH,
"Cancel", infofg, infobg);
BTCreate(&psbut[PS_BCENT], psW, 240, 153, 88, BUTTH,
"Center", infofg, infobg);
BTCreate(&psbut[PS_BMAX], psW, 240+88+5, 153, 87, BUTTH,
"Maxpect", infofg, infobg);
BTCreate(&psbut[PS_BPOSX], psW, 256-14, 190+13-8, 8,8, "", infofg, infobg);
BTCreate(&psbut[PS_BPOSY], psW, 256-14, 190+26-8, 8,8, "", infofg, infobg);
posxType = posyType = 0;
pos_inx = 1.0; pos_iny = 1.0; /* temporary bootstrapping... */
setPaper();
setScale();
XMapSubwindows(theDisp, psW);
}
/***************************************************/
void PSDialog(vis)
int vis;
{
if (vis) {
setScale();
if (firsttime) centerImage();
firsttime = 0;
CenterMapWindow(psW, psbut[PS_BOK].x + psbut[PS_BOK].w/2,
psbut[PS_BOK].y + psbut[PS_BOK].h/2, PSWIDE, PSHIGH);
}
else XUnmapWindow(theDisp, psW);
psUp = vis;
}
/***************************************************/
int PSCheckEvent(xev)
XEvent *xev;
{
/* check event to see if it's for one of our subwindows. If it is,
deal accordingly, and return '1'. Otherwise, return '0' */
int rv;
rv = 1;
if (!psUp) return 0;
if (xev->type == Expose) {
int x,y,w,h;
XExposeEvent *e = (XExposeEvent *) xev;
x = e->x; y = e->y; w = e->width; h = e->height;
/* throw away excess expose events for 'dumb' windows */
if (e->count > 0 &&
(e->window == xsDial.win || e->window == ysDial.win ||
e->window == pageF)) {}
else if (e->window == psW) drawPSD(x, y, w, h);
else if (e->window == xsDial.win) DRedraw(&xsDial);
else if (e->window == ysDial.win) DRedraw(&ysDial);
else if (e->window == pageF) drawPage();
else rv = 0;
}
else if (xev->type == ButtonPress) {
XButtonEvent *e = (XButtonEvent *) xev;
int i,old,x,y;
x = e->x; y = e->y;
if (e->button == Button1) {
if (e->window == psW) clickPSD(x,y);
else if (e->window == pageF) clickPage(x,y);
else if (e->window == xsDial.win || e->window == ysDial.win) {
if (e->window == xsDial.win) {
tracking = 1;
DTrack(&xsDial, x,y);
tracking = 0;
}
else if (e->window == ysDial.win) {
tracking = 2;
DTrack(&ysDial, x,y);
tracking = 0;
}
}
else rv = 0;
} /* button1 */
else rv = 0;
} /* button press */
else if (xev->type == KeyPress) {
XKeyEvent *e = (XKeyEvent *) xev;
char buf[128]; KeySym ks; XComposeStatus status;
int stlen;
stlen = XLookupString(e,buf,128,&ks,&status);
buf[stlen] = '\0';
if (e->window == psW) {
double dx, dy;
int movekey;
movekey = 0; dx = dy = 0.0;
if (ks==XK_Left || ks==XK_KP_4) { dx = -0.001; movekey = 1; }
else if (ks==XK_Right || ks==XK_KP_6) { dx = 0.001; movekey = 1; }
else if (ks==XK_Up || ks==XK_KP_8) { dy = -0.001; movekey = 1; }
else if (ks==XK_Down || ks==XK_KP_2) { dy = 0.001; movekey = 1; }
else if (stlen) {
if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
FakeButtonPress(&psbut[PS_BOK]);
}
else if (buf[0] == '\033') { /* ESC */
FakeButtonPress(&psbut[PS_BCANC]);
}
}
if (movekey) {
if (e->state & ShiftMask) { dx *= 10.0; dy *= 10.0; }
moveImage(pos_inx+dx, pos_iny+dy);
}
}
else rv = 0;
}
else rv = 0;
if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
XBell(theDisp, 50);
rv = 1; /* eat it */
}
return rv;
}
/***************************************************/
void PSSaveParams(fname, col)
char *fname;
int col;
{
filename = fname;
colorType = col;
}
/***************************************************/
void PSResize()
{
changedScale();
}
/***************************************************/
static void drawPSD(x,y,w,h)
int x,y,w,h;
{
char *title = "Save PostScript File...";
int i,cx;
XRectangle xr;
xr.x = x; xr.y = y; xr.width = w; xr.height = h;
XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
XSetForeground(theDisp, theGC, infofg);
XSetBackground(theDisp, theGC, infobg);
RBRedraw(orientRB,-1);
RBRedraw(paperRB,-1);
for (i=0; i<PS_NBUTTS; i++) BTRedraw(&psbut[i]);
CBRedraw(&lockCB);
ULineString(psW, "Orientation", orientRB->x-16, orientRB->y-3-DESCENT);
ULineString(psW, "Paper Size", paperRB->x-16, paperRB->y-3-DESCENT);
/* draw 'lock' arrows */
cx = 240 + 40; /* center of xsDial */
XDrawLine(theDisp, psW, theGC, lockCB.x, lockCB.y+5, cx+2, lockCB.y+5);
XDrawLine(theDisp, psW, theGC, cx+2, lockCB.y+5, cx+2, lockCB.y-2);
XDrawLine(theDisp, psW, theGC, lockCB.x, lockCB.y+9, cx-2, lockCB.y+9);
XDrawLine(theDisp, psW, theGC, cx-2, lockCB.y+9, cx-2, lockCB.y-2);
XDrawLine(theDisp, psW, theGC, cx-2-3, lockCB.y-2+3, cx, lockCB.y-2-2);
XDrawLine(theDisp, psW, theGC, cx+2+3, lockCB.y-2+3, cx, lockCB.y-2-2);
cx = 330 + 40; /* center of ysDial */
XDrawLine(theDisp, psW, theGC, lockCB.x+15, lockCB.y+5, cx-2, lockCB.y+5);
XDrawLine(theDisp, psW, theGC, cx-2, lockCB.y+5, cx-2, lockCB.y-2);
XDrawLine(theDisp, psW, theGC, lockCB.x+15, lockCB.y+9, cx+2, lockCB.y+9);
XDrawLine(theDisp, psW, theGC, cx+2, lockCB.y+9, cx+2, lockCB.y-2);
XDrawLine(theDisp, psW, theGC, cx-2-3, lockCB.y-2+3, cx, lockCB.y-2-2);
XDrawLine(theDisp, psW, theGC, cx+2+3, lockCB.y-2+3, cx, lockCB.y-2-2);
XDrawString(theDisp, psW, theGC, 10, 19, title, strlen(title));
ULineString(psW, "Position:", 240, 190);
drawPosStr();
ULineString(psW, "Size:", 240, 190+45);
drawSizeStr();
ULineString(psW, "Resolution:", 240, 190+90);
drawResStr();
XSetClipMask(theDisp, theGC, None);
}
/***************************************************/
static void drawPosStr()
{
int x,y;
double cmx, cmy, inx, iny;
char str[64], str1[64], *xst, *yst;
x = 256; y = 190 + 13;
switch (posxType) {
case 0: xst = "Left: "; inx = pos_inx; break;
case 1: xst = "Right:"; inx = psizex - (pos_inx + sz_inx); break;
case 2: xst = "X Mid:"; inx = pos_inx + sz_inx/2; break;
}
switch (posyType) {
case 0: yst = "Top: "; iny = pos_iny; break;
case 1: yst = "Bot: "; iny = psizey - (pos_iny + sz_iny); break;
case 2: yst = "Y Mid:"; iny = pos_iny + sz_iny/2; break;
}
cmx = inx * IN2CM;
cmy = iny * IN2CM;
sprintf(str, "%s %.3f\" (%.2fcm) ", xst, inx, cmx);
sprintf(str1, "%s %.3f\" (%.2fcm) ", yst, iny, cmy);
XSetForeground(theDisp, theGC, infofg);
XSetBackground(theDisp, theGC, infobg);
XSetFont(theDisp, theGC, monofont);
XDrawImageString(theDisp, psW, theGC, x, y, str, strlen(str));
XDrawImageString(theDisp, psW, theGC, x, y+13, str1, strlen(str1));
XSetFont(theDisp, theGC, mfont);
}
/***************************************************/
static void drawSizeStr()
{
int x,y;
double cmx, cmy;
char str[64], str1[64];
x = 256; y = 190+13+45;
cmx = sz_inx * IN2CM;
cmy = sz_iny * IN2CM;
sprintf(str, "%.3f\" x %.3f\" ", sz_inx, sz_iny);
sprintf(str1, "%.2fcm x %.2fcm ", cmx, cmy);
XSetForeground(theDisp, theGC, infofg);
XSetBackground(theDisp, theGC, infobg);
XSetFont(theDisp, theGC, monofont);
XDrawImageString(theDisp, psW, theGC, x, y, str, strlen(str));
XDrawImageString(theDisp, psW, theGC, x, y+13, str1, strlen(str1));
XSetFont(theDisp, theGC, mfont);
}
/***************************************************/
static void drawResStr()
{
int x,y;
char str[64];
x = 256; y = 190 + 13 + 90;
sprintf(str, "%ddpi x %ddpi ", dpix, dpiy);
XSetForeground(theDisp, theGC, infofg);
XSetBackground(theDisp, theGC, infobg);
XSetFont(theDisp, theGC, monofont);
XDrawImageString(theDisp, psW, theGC, x, y, str, strlen(str));
XSetFont(theDisp, theGC, mfont);
}
/***************************************************/
static void drawPage()
{
int i;
/* draw page */
XSetForeground(theDisp, theGC, infobg);
XFillRectangle(theDisp, pageF, theGC, pageRect.x+1, pageRect.y+1,
pageRect.width-1, pageRect.height-1);
XSetForeground(theDisp, theGC, infofg);
XDrawRectangle(theDisp, pageF, theGC, pageRect.x, pageRect.y,
pageRect.width, pageRect.height);
drawIRect(1);
}
/***************************************************/
static void clickPSD(x,y)
int x,y;
{
int i,j;
BUTT *bp;
/* check BUTTs */
for (i=0; i<PS_NBUTTS; i++) {
bp = &psbut[i];
if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
}
if (i<PS_NBUTTS) { /* found one */
if (BTTrack(bp)) doCmd(i);
}
/* check RBUTTs */
else if ((i=RBClick(orientRB,x,y)) >= 0) {
if (RBTrack(orientRB, i)) changedPaper();
}
else if ((i=RBClick(paperRB,x,y)) >= 0) {
if (RBTrack(paperRB, i)) changedPaper();
}
/* check CBUTTs */
else if (CBClick(&lockCB,x,y)) {
if (CBTrack(&lockCB) && lockCB.val) { /* turned on lock */
DSetVal(&ysDial, xsDial.val); /* copy xsDial.val to ysDial */
changedScale();
}
}
}
/***************************************************/
static void clickPage(mx,my)
int mx,my;
{
Window rW,cW;
int rx,ry,x,y;
unsigned int mask;
double offx, offy, newx, newy;
/* compute offset (in inches) between 'drag point' and
the top-left corner of the image */
offx = ((mx - pageRect.x) / in2pix) - pos_inx;
offy = ((my - pageRect.y) / in2pix) - pos_iny;
/* if clicked outside of image rectangle, ignore */
if (offx<0.0 || offy < 0.0 || offx>=sz_inx || offy >= sz_iny) return;
while (1) {
if (XQueryPointer(theDisp,pageF,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
if (!(mask & Button1Mask)) break; /* button released */
/* compute new pos_inx, pos_iny based on x,y coords */
newx = ((x-pageRect.x) / in2pix) - offx;
newy = ((y-pageRect.y) / in2pix) - offy;
moveImage(newx, newy);
}
}
}
/***************************************************/
static void doCmd(cmd)
int cmd;
{
switch (cmd) {
case PS_BOK: writePS(); PSDialog(0); break;
case PS_BCANC: PSDialog(0); break;
case PS_BCENT: drawIRect(0);
centerImage();
drawIRect(1);
drawPosStr();
break;
case PS_BMAX: drawIRect(0);
maxImage();
drawIRect(1);
drawPosStr();
drawSizeStr();
drawResStr();
break;
case PS_BPOSX: posxType = (posxType + 1) % 3;
drawPosStr();
break;
case PS_BPOSY: posyType = (posyType + 1) % 3;
drawPosStr();
break;
default: break;
}
}
/***************************************************/
static void changedScale()
{
double oldx,oldy;
drawIRect(0);
if (lockCB.val) {
if (tracking == 1) DSetVal(&ysDial, xsDial.val);
else if (tracking == 2) DSetVal(&xsDial, ysDial.val);
}
oldx = pos_inx; oldy = pos_iny;
setScale();
drawIRect(1);
if (pos_inx != oldx || pos_iny != oldy ||
posxType != 0 || posyType != 0) drawPosStr();
drawSizeStr();
drawResStr();
XFlush(theDisp);
}
/***************************************************/
static void setScale()
{
double hsx, hsy;
sz_inx = (double) eWIDE / PIX2INCH * (xsDial.val / 100.0);
sz_iny = (double) eHIGH / PIX2INCH * (ysDial.val / 100.0);
/* round to integer .001ths of an inch */
sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
dpix = (int) (PIX2INCH / (xsDial.val / 100.0));
dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));
/* make sure 'center' of image is still on page */
hsx = sz_inx/2; hsy = sz_iny/2;
RANGE(pos_inx, -hsx, psizex-hsx);
RANGE(pos_iny, -hsy, psizey-hsy);
/* round to integer .001ths of an inch */
pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
}
/***************************************************/
static void changedPaper()
{
setPaper();
XClearWindow(theDisp, pageF);
centerImage();
drawPosStr();
drawPage();
}
/***************************************************/
static void setPaper()
{
double tmp;
psizex = paperSize[RBWhich(paperRB)][0];
psizey = paperSize[RBWhich(paperRB)][1];
in2pix = (double) PMAX / psizey;
if (RBWhich(orientRB)==ORNT_LAND) {
tmp = psizex; psizex = psizey; psizey = tmp;
}
pageRect.x = (int) ((PMAX/2) - ((psizex/2.0) * in2pix));
pageRect.y = (int) ((PMAX/2) - ((psizey/2.0) * in2pix));
pageRect.width = (int) (psizex * in2pix);
pageRect.height = (int) (psizey * in2pix);
}
/***************************************************/
static void drawIRect(draw)
int draw;
{
int x,y,w,h;
XRectangle xr;
x = pageRect.x + (int) (pos_inx * in2pix);
y = pageRect.y + (int) (pos_iny * in2pix);
w = sz_inx * in2pix;
h = sz_iny * in2pix;
xr.x = pageRect.x + 1;
xr.y = pageRect.y + 1;
xr.width = pageRect.width - 1;
xr.height = pageRect.height - 1;
if (draw) XSetForeground(theDisp, theGC, infofg);
else XSetForeground(theDisp, theGC, infobg);
XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
XDrawRectangle(theDisp, pageF, theGC, x, y, w, h);
XDrawLine(theDisp, pageF, theGC, x, y, x+w, y+h);
XDrawLine(theDisp, pageF, theGC, x, y+h, x+w, y);
XSetClipMask(theDisp, theGC, None);
}
/***************************************************/
static void centerImage()
{
pos_inx = psizex/2 - sz_inx/2;
pos_iny = psizey/2 - sz_iny/2;
/* round to integer .001ths of an inch */
pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
}
/***************************************************/
static void maxImage()
{
double scx, scy;
sz_inx = psizex - 1.0; /* half inch margin on all sides */
sz_iny = psizey - 1.0;
/* choose the smaller scaling factor */
scx = sz_inx / eWIDE;
scy = sz_iny / eHIGH;
if (scx < scy) { sz_iny = eHIGH * scx; }
else { sz_inx = eWIDE * scy; }
DSetVal(&xsDial, (int) ((100 * (sz_inx * PIX2INCH) / eWIDE) + .5));
DSetVal(&ysDial, xsDial.val);
sz_inx = (double) eWIDE / PIX2INCH * (xsDial.val / 100.0);
sz_iny = (double) eHIGH / PIX2INCH * (ysDial.val / 100.0);
/* round to integer .001ths of an inch */
sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
dpix = (int) (PIX2INCH / (xsDial.val / 100.0));
dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));
pos_inx = psizex/2 - sz_inx/2;
pos_iny = psizey/2 - sz_iny/2;
/* round to integer .001ths of an inch */
pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
}
/***************************************************/
static void moveImage(newx,newy)
double newx, newy;
{
double hsx, hsy;
hsx = sz_inx/2; hsy = sz_iny/2;
/* round to integer .001ths of an inch */
newx = floor(newx * 1000.0 + 0.5) / 1000.0;
newy = floor(newy * 1000.0 + 0.5) / 1000.0;
/* keep center of image within page limits */
RANGE(newx, -hsx, psizex-hsx);
RANGE(newy, -hsy, psizey-hsy);
if (newx != pos_inx || newy != pos_iny) { /* moved */
drawIRect(0);
pos_inx = newx;
pos_iny = newy;
drawIRect(1);
drawPosStr();
}
}
/***************************************************/
static void writePS()
{
FILE *fp;
int i, j, q, err, rpix, gpix, bpix, nc;
int iw, ih, ox, oy, slen, lwidth, bits, colorps;
byte *inpix, *bwpic, *rmap, *gmap, *bmap;
inpix = epic; bwpic = NULL; rmap = r; gmap = g; bmap = b;
nc = numcols;
fp = OpenOutFile(filename);
if (!fp) return;
WaitCursor();
bwpic = HandleBWandReduced(colorType, &nc, &rmap, &gmap, &bmap);
if (bwpic) inpix = bwpic;
/* monocity check. if the image is mono, save it that way to save space */
if (colorType == F_FULLCOLOR || colorType == F_REDUCED) {
for (i=0; i<nc && rmap[i]==gmap[i] && rmap[i]==bmap[i]; i++);
if (i==nc) colorType = F_GREYSCALE; /* made it all the way through */
}
/* printed image will have size iw,ih (in picas) */
iw = (int) (sz_inx * 72.0 + 0.5);
ih = (int) (sz_iny * 72.0 + 0.5);
/* compute offset to bottom-left of image (in picas) */
ox = (int) (pos_inx * 72.0 + 0.5);
oy = (int) ((psizey - (pos_iny + sz_iny)) * 72.0 + 0.5);
/*** write PostScript header ***/
fprintf(fp,"%%!PS-Adobe-2.0 EPSF-2.0\n");
fprintf(fp,"%%%%Title: %s\n",filename);
fprintf(fp,"%%%%Creator: XV %s - by John Bradley\n",REVDATE);
if (RBWhich(orientRB)==ORNT_LAND) /* Landscape mode */
fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n",
(int) (pos_iny * 72.0 + 0.5),
(int) (pos_inx * 72.0 + 0.5),
(int) (pos_iny * 72.0 + 0.5) + iw,
(int) (pos_inx * 72.0 + 0.5) + ih);
else
fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n", ox, oy, ox+iw, oy+ih);
fprintf(fp,"%%%%Pages: 1\n");
fprintf(fp,"%%%%DocumentFonts:\n");
fprintf(fp,"%%%%EndComments\n");
switch (colorType) {
case F_FULLCOLOR:
case F_REDUCED: slen = eWIDE*3; bits = 8; colorps = 1; break;
case F_GREYSCALE: slen = eWIDE; bits = 8; colorps = 0; break;
case F_BWDITHER: slen = (eWIDE+7)/8; bits = 1; colorps = 0; break;
default: /* never happen */
slen = eWIDE*3; bits = 8; colorps = 1; break;
}
epsPreview(fp, inpix, colorType);
fprintf(fp,"%%%%EndProlog\n\n");
fprintf(fp,"%% remember original state\n");
fprintf(fp,"/origstate save def\n\n");
fprintf(fp,"%% build a temporary dictionary\n");
fprintf(fp,"10 dict begin\n\n");
fprintf(fp,"%%%%Page: 1 1\n");
fprintf(fp,"%% define string to hold a scanline's worth of data\n");
fprintf(fp,"/pix %d string def\n\n", slen);
if (RBWhich(orientRB)==ORNT_LAND) { /* Landscape mode */
fprintf(fp,"%% print in landscape mode\n");
fprintf(fp,"90 rotate 0 %d translate\n\n",(int) (-psizey*72.0));
}
fprintf(fp,"%% lower left corner\n");
fprintf(fp,"%d %d translate\n\n",ox,oy);
fprintf(fp,"%% size of image (on paper, in 1/72inch coords)\n");
fprintf(fp,"%d %d scale\n\n",iw,ih);
if (colorType == F_FULLCOLOR || colorType == F_REDUCED)
psColorImage(fp);
fprintf(fp,"%% dimensions of data\n");
fprintf(fp,"%d %d %d\n\n",eWIDE,eHIGH,bits);
fprintf(fp,"%% mapping matrix\n");
fprintf(fp,"[%d 0 0 %d 0 %d]\n\n", eWIDE, -eHIGH, eHIGH);
fprintf(fp,"{currentfile pix readhexstring pop}\n");
if (colorps) fprintf(fp,"false 3 colorimage\n");
else fprintf(fp,"image\n");
/* write the actual image data */
if (colorType == F_BWDITHER) { /* 1-bit BWDither code */
err = writeBWStip(fp, inpix, "");
}
else { /* FULLCOLOR, REDUCED, and GREYSCALE handling code */
err = 0;
for (i=0; i<eHIGH && err != EOF; i++) {
lwidth = 0;
putc('\n',fp);
if ((i&0x1f) == 0) WaitCursor();
for (j=0; j<eWIDE && err != EOF; j++) {
rpix = rmap[*inpix];
gpix = gmap[*inpix];
bpix = bmap[*inpix];
if (colorps) {
err = fprintf(fp,"%02x%02x%02x",rpix,gpix,bpix);
lwidth+=6;
}
else { /* greyscale */
q = (rpix*21 + gpix*32 + bpix*11) / 64;
err = fprintf(fp,"%02x", q);
lwidth+=2;
}
if (lwidth>70) { putc('\n',fp); lwidth = 0; }
inpix++;
}
}
}
fprintf(fp,"\n\nshowpage\n\n");
fprintf(fp,"%% stop using temporary dictionary\n");
fprintf(fp,"end\n\n");
fprintf(fp,"%% restore original state\n");
fprintf(fp,"origstate restore\n\n");
fprintf(fp,"%%%%Trailer\n");
if (bwpic) free(bwpic);
if (CloseOutFile(fp, filename, (err==EOF)) == 0) {
DirBox(0);
LoadCurrentDirectory(); /* wrote file: rescan directory */
}
SetCursors(-1);
}
/**********************************************/
static void psColorImage(fp)
FILE *fp;
{
/* spits out code that checks if the PostScript device in question
knows about the 'colorimage' operator. If it doesn't, it defines
'colorimage' in terms of image (ie, generates a greyscale image from
RGB data) */
fprintf(fp,"%% see if we have the 'colorimage' operator.\n");
fprintf(fp,"%% define one if we don't\n");
fprintf(fp,"/colorimage where %% do we know about 'colorimage'?\n");
fprintf(fp," { pop } %% yes: pop off the 'dict' returned\n");
fprintf(fp," { %% no: define one\n");
fprintf(fp," /str1 1 string def\n");
fprintf(fp," /str3 3 string def\n");
fprintf(fp," /colorimage\n");
fprintf(fp," { pop pop %% pop off 'false', '3' operands\n");
fprintf(fp," pop %% pop off old 'readhexstring' proc\n");
fprintf(fp," %% and define a new one for 'image'\n");
fprintf(fp," { currentfile str3 readhexstring pop pop\n");
fprintf(fp," str1 0 %% for the 'put' below\n");
fprintf(fp," str3 0 get 20 mul %% Red\n");
fprintf(fp," str3 1 get 32 mul %% Green\n");
fprintf(fp," str3 2 get 12 mul %% Blue\n");
fprintf(fp," add add 64 idiv %% I = .5G + .31R + .18B\n");
fprintf(fp," put str1 %% str1 = intensity of R,G,B triplet\n");
fprintf(fp," } image\n");
fprintf(fp," } def %% end of colorimage def\n");
fprintf(fp," } ifelse %% end of 'false' case\n");
fprintf(fp,"\n");
}
/**********************************************/
static void epsPreview(fp, pic, colorType)
FILE *fp;
byte *pic;
int colorType;
{
byte *prev;
/* put in an EPSI preview */
if (colorType != F_BWDITHER) { /* have to generate a preview */
prev = (byte *) malloc(eWIDE * eHIGH);
if (!prev) {
fprintf(stderr,"Unable to malloc in epsPreview\n");
return;
}
FSDither(epic, eWIDE, eHIGH, prev);
}
else prev = pic;
fprintf(fp,"%%%%BeginPreview: %d %d %d %d\n", eWIDE, eHIGH, 1,
(eWIDE/(72*4) + 1) * eHIGH);
writeBWStip(fp, prev, "% ");
fprintf(fp,"%%%%EndPreview\n");
if (colorType == F_BWDITHER) free(prev);
}
/***********************************/
static int writeBWStip(fp, pic, prompt)
FILE *fp;
byte *pic;
char *prompt;
{
/* write the given 'pic' (B/W stippled, 1 byte per pixel, 0=blk,1=wht)
out as hexadecimal, max of 72 hex chars per line.
returns '0' if everythings fine, 'EOF' if writing failed */
int err, i, j, lwidth;
byte outbyte, bitnum, bit;
err = 0;
for (i=0; i<eHIGH && err != EOF; i++) {
fprintf(fp, "%s", prompt);
outbyte = bitnum = lwidth = 0;
if ((i&0x3f) == 0) WaitCursor();
for (j=0; j<eWIDE && err != EOF; j++) {
bit = *pic;
outbyte = (outbyte<<1) | ((~bit)&0x01);
bitnum++;
if (bitnum==8) {
err = fprintf(fp,"%02x",outbyte);
lwidth+=2;
outbyte = bitnum = 0;
}
if (lwidth>=72 && j+1<eWIDE) { fprintf(fp, "\n%s", prompt); lwidth = 0; }
pic++;
}
if (bitnum) { /* few bits left over... */
for ( ; bitnum<8; bitnum++) outbyte <<= 0;
err = fprintf(fp,"%02x",outbyte);
lwidth+=2;
}
fprintf(fp, "\n");
}
return err;
}